export default class Zignal {
  constructor(initialValue) {
    this.value = initialValue;
    this.subscribers = new Set();
  }

  get() {
    return this.value;
  }

  set(newValue) {
    if (this.value !== newValue) {
      this.value = newValue;
      this.notify();
    }
  }

  subscribe(callback = () => {}) {
    this.subscribers.add(callback);
    return () => this.subscribers.delete(callback);
  }

  notify() {
    this.subscribers.forEach((callback) => callback(this.value));
  }
}

export class ComputedZignal {
  constructor(computeFn, dependencies) {
    this.computeFn = computeFn;
    this.dependencies = dependencies;
    this.value = computeFn();

    this.unsubscribeFns = dependencies.map((dep) =>
      dep.subscribe(() => {
        const newValue = this.computeFn();
        if (this.value !== newValue) {
          this.value = newValue;
          this.notify();
        }
      })
    );

    this.subscribers = new Set();
  }

  get() {
    return this.value;
  }

  subscribe(callback = () => {}) {
    this.subscribers.add(callback);
    return () => this.subscribers.delete(callback);
  }

  notify() {
    this.subscribers.forEach((callback) => callback(this.value));
  }

  dispose() {
    this.unsubscribeFns.forEach((unsubscribe) => unsubscribe());
  }
}

export const zignal = (initialValue) => new Zignal(initialValue);
export const computed = (computeFn, dependencies) => new ComputedZignal(computeFn, dependencies);